/*
 * Copyright (C) 2007,2008  Jonathan Hendler
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 * 
 * The authors can be contacted at: 
 * @author Jonathan Hendler [jonathan DOT hendler AT google DOT com]
 * 
 * @license GPLv2
 */
#include "nymrl_message.h"


inline  nyml_header_struct * nymrl_get_header_from_string(char * request_string, int _free){
	int size = sizeof( nyml_header_struct);
	nyml_header_struct * return_struct =  ( nyml_header_struct * ) malloc(size);
	size_t data_size = ( (strlen(request_string) * sizeof(char) ) - ( ( strlen(NYMRL_HEADER)-5) * sizeof(char)  ) );
	//malloc the data section of the string
	return_struct->dat  = (char *) malloc(data_size +1);
	
	sscanf(request_string,NYMRL_HEADER_SCAN,
			&return_struct->nid,
			return_struct->rel,
			&return_struct->time,
			return_struct->msid,
			return_struct->rmid,
			&return_struct->chck,
			&return_struct->enc,
			(int *)&return_struct->fwd,
			return_struct->auth,
			return_struct->dat,
			return_struct->act
			);
	
 	if (return_struct->dat){
 		nymrl_raw_url_decode(return_struct->dat, strlen(return_struct->dat));
 	}

	if ((_free == TRUE) && (request_string)) free(request_string);
	return return_struct;
}

inline void nymrl_free_header_struct( nyml_header_struct * this){
	if (this->dat) free(this->dat);
	if (this) free(this);
}

inline char * nymrl_get_string_from_header( nyml_header_struct * this, int _free){
	int size;
	int size_,a,b,c,d, total;
	char * return_string;
	char * new_dat = NULL;
	
	if (this->dat) {
		new_dat = nymrl_raw_url_encode(this->dat,strlen(this->dat),&size_);
	}
	 
 	a = (int) (strlen(new_dat) * sizeof(char) );
 	b= (int)strlen(NYMRL_HEADER) * sizeof(char) ;
 	c = (int) ( 3 * sizeof(NYMRL_ID));
 	d = (int)( 6 * NYMRL_HEADER_STR_SIZE) ;
    total =  (int)(a + b + c + d);
//	
 	return_string = (char *) malloc(total);
 	sprintf(return_string,NYMRL_HEADER,this->nid,this->rel,this->time,this->msid,this->rmid,this->chck,this->enc,this->fwd,this->auth,new_dat,this->act);
	//cleanup
 	if (new_dat && (_free == TRUE)) free(new_dat);
	if (_free == TRUE) nymrl_free_header_struct(this);
	
	return return_string;
}


inline void * nymrl_new_header(
		NYMRL_ID nid, 
		char * rel,
		int time,
		char * msid,
		char * rmid,
		unsigned long chck,
		int enc,
		enum nymrl_fwd fwd,
		char * auth,
		char * dat,
		char * act,
		const char * string_or_struct,
		int _free ){
	
	char * return_string;
    char * new_dat;
	int size,size2;
    nyml_header_struct * return_struct;
    
	
	if ((string_or_struct != NULL) && strcmp(string_or_struct,"string")==0){
		new_dat = nymrl_raw_url_encode(dat,strlen(dat),&size2);
	    size = ((6*sizeof(NYMRL_ID)) + (5*NYMRL_HEADER_STR_SIZE) + (size2 * sizeof(char)) );
	   // printf("\n malloc %d",size);
	    
        return_string = malloc(size);
		sprintf(return_string,NYMRL_HEADER,nid,rel,time,msid,rmid,chck,enc,fwd,auth,new_dat,act);
		if(new_dat) free(new_dat);
		return return_string;
	} else {
		size = sizeof( nyml_header_struct);
		return_struct =  (nyml_header_struct *) malloc(size);
		return_struct->dat = (char * ) malloc( (strlen(dat)+1) * sizeof(char));
	
		strcpy(return_struct->rel, rel);
		if ((_free == TRUE) && rel) free(rel);
		
		return_struct->chck = chck;
		return_struct->enc = enc;
		return_struct->nid = nid;
		return_struct->fwd = fwd;
		return_struct->time = time;
		
		strcpy(return_struct->msid, msid);
		if (_free == TRUE) free(msid);
	 
		strcpy(return_struct->rmid, rmid);
		if (_free == TRUE) free(rmid);
		
		strcpy(return_struct->dat, dat);
		if (_free == TRUE) free(dat);
		
		strcpy(return_struct->auth, auth);
		if (_free == TRUE) free(auth);
		
		strcpy(return_struct->act, act);
		if (_free == TRUE) free(act);
	
		return return_struct;
	}
}

//convert message string to JSON object

//convert JSON object to message string
inline char * nymrl_encrypt(char * string){
	return string;
}

inline char * nymrl_decrypt(char * string){
	
	
	return string;
	
}

////////////////////////////////////////////////////////////////////////
//// CURL STUFF

static inline void *nymrl_curl_realloc(void *ptr, size_t size)
{
  /* There might be a realloc() out there that doesn't like reallocing
       NULL pointers, so we take care of it here */
  if(ptr)
      return realloc(ptr, size);
  else
      return malloc(size);
}

static inline size_t  nymrl_curl_memory_callback(void *ptr, size_t size, size_t nmemb, void *data)
  {
    size_t realsize = size * nmemb;
    struct nymrl_curl_struct *mem = (struct nymrl_curl_struct *)data;
  
    mem->memory = (char *)nymrl_curl_realloc(mem->memory, mem->size + realsize + 1);
    if (mem->memory) {
      memcpy(&(mem->memory[mem->size]), ptr, realsize);
      mem->size += realsize;
      mem->memory[mem->size] = 0;
    }
    return realsize;
}


/**
forward headers and cookies
@todo do this in  multithreaded way http://curl.planetmirror.com/libcurl/c/libcurl-multi.html

*/
inline char * nymrl_curl_post(char * url, char * post_data, char * cookies){
	CURL *curl;
	CURLcode res;
	struct nymrl_curl_struct chunk;
	struct curl_slist *headerlist = NULL;
	//char * post_data_p = post_data;
	
	//input
	chunk.memory=NULL; /* we expect realloc(NULL, size) to work */
	chunk.size = 0;    /* no data at this point */

	curl = curl_easy_init();

	if(curl) {
		curl_easy_setopt(curl, CURLOPT_URL,url);
		/* send all data to this function  */
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, nymrl_curl_memory_callback);
 		
		if ((cookies != NULL)){	
 			headerlist = curl_slist_append(headerlist,cookies);
 			curl_easy_setopt(curl,CURLOPT_HTTPHEADER,headerlist);
		}	

		/* we pass our 'chunk' struct to the callback function */
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
		curl_easy_setopt(curl, CURLOPT_USERAGENT, NYMRL_URL_CURL_HTTP_AGENT_NAME);
		
		//TODO
		if (post_data != NULL){
			//http://curl.planetmirror.com/libcurl/c/libcurl-tutorial.html
			curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data);
		}
		
		res = curl_easy_perform(curl);
		
		/* always cleanup */
		curl_easy_cleanup(curl);
	}
	
	if(chunk.memory){
 		//free(chunk.memory);
		return (char *) chunk.memory;
	} else {
		return (char *) "";
	}
}

/**
@see master_curl_post
*/
inline char * nymrl_curl_get(char * url, char * cookies){
	return nymrl_curl_post(url, NULL,cookies);
}

/**
used to post or get content
doesn't care about the content, just forwards it and prints the response
*/
inline int nymrl_curl_blind_forward(char * url, char * post_data, char * cookies){
	char * remote_page = nymrl_curl_post( url,  post_data,cookies);
	printf("<br />Remote page: <pre>%s</pre>",remote_page);
	free(remote_page);
	return 0;	
}

//TODO
/**
 * validates NYMRL strings
 * */
inline int nymrl_valid_string(char * string){
	
	return TRUE;
}
